﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using CommonLib;

namespace MLO
{
    public static class GenSource
    {
        public static DataSet all_data = new DataSet("all_data");

        public static List<Frame> all_frames = new List<Frame>();
        public static List<Frame> situations = new List<Frame>();
        public static List<Frame> exemplars = new List<Frame>();
        public static List<Frame> prototypes = new List<Frame>();

        //процедура извлечения всех родительских слотов
        public static List<Slot> GetHeritSlots(string frame_name)
        {
            List<Slot> result = new List<Slot>();
            Frame searched = GenSource.all_frames.Find(o => o.Name == frame_name);
            if (searched != null)
            {
                foreach (Slot slt in searched.GetSlots())
                {
                    if (slt.Type != SlotType.AKO)
                        result.Add(slt);
                }
                if (searched.GetSlots(SlotType.AKO).Count > 0)
                {
                    foreach (Slot slt in GetHeritSlots(((Slot)searched.GetSlots(SlotType.AKO)[0]).Subframe.Name))                        
                        result.Add(slt);
                }
            }
            return result;
        }

        //процедура поиска привязавшихся к прототипу экземпляров
        public static List<Frame> BindSubFrames(string frame_name)
        {
            Frame frm = GenSource.prototypes.Find(o => o.Name == frame_name);
            List<Frame> result = new List<Frame>();
            if (frm != null)
            {
                foreach (Frame ex_frm in GenSource.exemplars)
                {
                    bool add = true;
                    int i = 0;
                    List<ISlot> prttp_slots = frm.GetSlots(SlotType.Regular);
                    prttp_slots.AddRange(frm.GetSlots(SlotType.SubFrame));
                    prttp_slots.AddRange(frm.GetSlots(SlotType.Production));
                    while (add && i < prttp_slots.Count)
                    {
                        Slot prttp_slt = (Slot)prttp_slots[i];
                        Slot ex_slt = (Slot)ex_frm.SearchSlot(prttp_slt.Name);
                        add = add && ex_slt != null && SlotEquals(prttp_slt, ex_slt);
                        i++;
                    }
                    if (add)
                        result.Add(ex_frm);
                }
            }
            return result;
        }

        //процедурка проверки соответствия слотов прототипа и экземпляра
        public static bool SlotEquals(Slot prttp_slt, Slot ex_slt)
        {
            bool result = true;
            result = prttp_slt != null && ex_slt != null &&
                 prttp_slt.Name == ex_slt.Name && prttp_slt.Type == ex_slt.Type;
            if (result)
            {
                switch (prttp_slt.Type)
                {
                    case SlotType.SubFrame:
                        Frame ParentSubFrame = (Frame)ex_slt.Subframe;
                        if (exemplars.Contains(ParentSubFrame))
                            ParentSubFrame = prototypes.Find(o => o.Name == (ParentSubFrame.GetSlots(SlotType.AKO)[0] as Slot).Subframe.Name);
                        result = (Frame)prttp_slt.Subframe == ParentSubFrame;
                        break;
                    case SlotType.Regular:
                        switch (prttp_slt.Inherit)
                        {
                            case TypeInherit.Same:
                                result = ex_slt.Default.ToString() == prttp_slt.Default.ToString();
                                break;
                            case TypeInherit.Overwrite:
                                result = prttp_slt.Domain.Contains(ex_slt.Default.ToString());
                                break;
                            case TypeInherit.Range:
                                result = prttp_slt.Domain.Contains(ex_slt.Default.ToString(), prttp_slt.Default.ToString());
                                break;
                        }
                        break;
                    case SlotType.Production:
                        //TODO
                        break;
                }
            }
            return result;
        }
    }
}
